new credentials uploading feature

rm req json, not saving file, styled button a bit

skinny controller fat model

minor spacing mistake

build user credentials fixed mass assignment issue

undo mass assignment variables

spec in progress

spec

fixed exception issue

json fixtures

slight change to test

added test to assert credentials created for current user only

added tests to satisfy requirements

refined import method

added status 422

saving two lines of code

one more test

fixed small bug, words changed

minor change in test

styled file upload button

deleted unnecessary spec

switched to modal format

made modal more presentable

minor change to modal

fix indentation issue

ok nested correctly within form tag

Judy Ngai 8 years ago
parent
commit
26e776db4d

+ 20 - 0
app/controllers/user_credentials_controller.rb

@@ -14,6 +14,26 @@ class UserCredentialsController < ApplicationController
14 14
     end
15 15
   end
16 16
 
17
+  def import
18
+    if params[:file]
19
+      file = params[:file]
20
+      content = JSON.parse(file.read)
21
+      new_credentials = content.map do |hash|
22
+        current_user.user_credentials.build(hash.slice("credential_name", "credential_value", "mode"))
23
+      end
24
+
25
+      respond_to do |format|
26
+        if new_credentials.map(&:save).all?
27
+          format.html { redirect_to user_credentials_path, notice: "The file was successfully uploaded."}
28
+        else
29
+          format.html { redirect_to user_credentials_path, notice: 'One or more of the uploaded credentials was not imported due to an error. Perhaps an existing credential had the same name?'}
30
+        end
31
+      end
32
+    else
33
+      redirect_to user_credentials_path, notice: "No file was chosen to be uploaded." 
34
+    end
35
+  end
36
+
17 37
   def new
18 38
     @user_credential = current_user.user_credentials.build
19 39
 

+ 22 - 0
app/views/user_credentials/index.html.erb

@@ -39,6 +39,28 @@
39 39
       <div class="btn-group">
40 40
         <%= link_to new_user_credential_path, class: "btn btn-default" do %><span class="glyphicon glyphicon-plus"></span> New Credential<% end %>
41 41
         <%= link_to user_credentials_path(format: :json), class: "btn btn-default" do %><span class="glyphicon glyphicon-cloud-download"></span> Download Credentials<% end %>
42
+        <%= link_to '#', data: { toggle: 'modal', target: '#credentials-upload' }, class: "btn btn-default credentials-upload-button" do %><span class="glyphicon glyphicon-upload"></span> Upload Credentials<% end %>
43
+      </div>
44
+
45
+      <div id="credentials-upload" class="modal fade" tabindex="-1" role="dialog">
46
+        <div class="modal-dialog">
47
+          <div class="modal-content">
48
+            <%= form_tag import_user_credentials_path, multipart: true do %>
49
+              <div class="modal-header">
50
+                <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
51
+                <h4 class="modal-title">Upload Credentials</h4>
52
+              </div>
53
+              <div class="modal-body">
54
+                <p>Upload a credentials file that you have previously exported from a Huginn instance.</p>
55
+                <%= file_field_tag :file, class: 'form-control' %>
56
+              </div>
57
+              <div class="modal-footer">
58
+                <%= button_tag 'Cancel', class: 'btn btn-default', 'data-dismiss' => 'modal' %>
59
+                <%= submit_tag 'Upload', class: 'btn btn-primary' %>
60
+              </div>
61
+            <% end %>
62
+          </div>
63
+        </div>
42 64
       </div>
43 65
     </div>
44 66
   </div>

+ 5 - 1
config/routes.rb

@@ -48,7 +48,11 @@ Huginn::Application.routes.draw do
48 48
     resource :diagram, :only => [:show]
49 49
   end
50 50
 
51
-  resources :user_credentials, :except => :show
51
+  resources :user_credentials, :except => :show do
52
+    collection do
53
+      post :import
54
+    end
55
+  end
52 56
 
53 57
   resources :services, :only => [:index, :destroy] do
54 58
     member do

+ 21 - 0
spec/controllers/user_credentials_controller_spec.rb

@@ -10,6 +10,7 @@ describe UserCredentialsController do
10 10
 
11 11
   before do
12 12
     sign_in users(:bob)
13
+    @file = fixture_file_upload('user_credentials.json')
13 14
   end
14 15
 
15 16
   describe "GET index" do
@@ -30,6 +31,26 @@ describe UserCredentialsController do
30 31
     end
31 32
   end
32 33
 
34
+  describe "Post import" do
35
+    it "asserts user credentials were created for current user only" do
36
+      post :import, :file => @file
37
+      expect(controller.current_user.id).to eq(users(:bob).id)
38
+      expect(controller.current_user.user_credentials).to eq(users(:bob).user_credentials)
39
+    end
40
+
41
+    it "asserts that primary id in json file is ignored" do
42
+      post :import, :file => @file
43
+      expect(controller.current_user.user_credentials.last.id).not_to eq(24)
44
+    end
45
+
46
+    it "duplicate credential name shows an error that it is not saved" do
47
+      file1 = fixture_file_upload('multiple_user_credentials.json')
48
+      post :import, :file => file1
49
+      expect(flash[:notice]).to eq("One or more of the uploaded credentials was not imported due to an error. Perhaps an existing credential had the same name?")
50
+      expect(response).to redirect_to(user_credentials_path)
51
+    end
52
+  end
53
+
33 54
   describe "POST create" do
34 55
     it "creates UserCredentials for the current user" do
35 56
       expect {

+ 38 - 0
spec/fixtures/multiple_user_credentials.json

@@ -0,0 +1,38 @@
1
+[
2
+  {
3
+    "id": 23,
4
+    "user_id": 30,
5
+    "credential_name": "Google_api_key",
6
+    "credential_value": "gcperfxrtqymqmluvskxzyiyxxfnjduzncoukyqehkrkamofwz",
7
+    "created_at": "2016-04-01 10:50:59 -0700",
8
+    "updated_at": "2016-04-01 10:50:59 -0700",
9
+    "mode": "text"
10
+  },
11
+  {
12
+    "id": 24,
13
+    "user_id": 30,
14
+    "credential_name": "twitter_secret_key",
15
+    "credential_value": "jhpswiebwhbrnabgkbvczrwcyxblxtyvvlvkhuoudjalcqmlwz",
16
+    "created_at": "2016-04-01 10:50:59 -0700",
17
+    "updated_at": "2016-04-01 10:50:59 -0700",
18
+    "mode": "text"
19
+  },
20
+  {
21
+    "id": 23,
22
+    "user_id": 30,
23
+    "credential_name": "Google_api_key",
24
+    "credential_value": "gcperfxrtqymqmluvskxzyiyxxfnjduzncoukyqehkrkamofwz",
25
+    "created_at": "2016-04-01 10:50:59 -0700",
26
+    "updated_at": "2016-04-01 10:50:59 -0700",
27
+    "mode": "text"
28
+  },
29
+  {
30
+    "id": 24,
31
+    "user_id": 30,
32
+    "credential_name": "twitter_secret_key",
33
+    "credential_value": "jhpswiebwhbrnabgkbvczrwcyxblxtyvvlvkhuoudjalcqmlwz",
34
+    "created_at": "2016-04-01 10:50:59 -0700",
35
+    "updated_at": "2016-04-01 10:50:59 -0700",
36
+    "mode": "text"
37
+  }
38
+]

+ 20 - 0
spec/fixtures/user_credentials.json

@@ -0,0 +1,20 @@
1
+[
2
+  {
3
+    "id": 23,
4
+    "user_id": 30,
5
+    "credential_name": "Google_api_key",
6
+    "credential_value": "gcperfxrtqymqmluvskxzyiyxxfnjduzncoukyqehkrkamofwz",
7
+    "created_at": "2016-04-01 10:50:59 -0700",
8
+    "updated_at": "2016-04-01 10:50:59 -0700",
9
+    "mode": "text"
10
+  },
11
+  {
12
+    "id": 24,
13
+    "user_id": 30,
14
+    "credential_name": "twitter_secret_key",
15
+    "credential_value": "jhpswiebwhbrnabgkbvczrwcyxblxtyvvlvkhuoudjalcqmlwz",
16
+    "created_at": "2016-04-01 10:50:59 -0700",
17
+    "updated_at": "2016-04-01 10:50:59 -0700",
18
+    "mode": "text"
19
+  }
20
+]